﻿using Microsoft.AspNetCore.Authorization;
using Rswl.Common.Core.User.Aggregate.ValueObject;

namespace Rswl.Common.Application.User
{
    public class AdminRequirement : IAuthorizationRequirement
    {
        public string PolicyName { get; private set; }
        public AdminRequirement(string policyName="")
        {
            PolicyName = policyName;
        }
    }
    public class AdminRequirementHandler : AuthorizationHandler<AdminRequirement>
    {

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AdminRequirement requirement)
        {
            if (context.User.Claims.Count() <= 0)
            {
                context.Fail();
            }

            var policyName = requirement.PolicyName;
            var policies = GetPolicy(context, requirement);

            var policy = policies[policyName];

            if (policy == null)
            {
                throw new ApplicationException("policy is valid,please set ");
            }
            policy.Invoke();
            return Task.CompletedTask;
        }

        Dictionary<string,Action>GetPolicy(AuthorizationHandlerContext context, AdminRequirement requirement)
        {
            Dictionary<string, Action> policies = new Dictionary<string, Action>();
            policies["admin"] = () => AdminPolicy(context, requirement);
            policies["vip"] = () => VipPolicy(context, requirement);

            return policies;
        }

        void AdminPolicy(AuthorizationHandlerContext context, AdminRequirement requirement)
        {
            var role = context.User.Claims.FirstOrDefault(c => c.Type == "Role")?.Value;
            if (role == ((int)UserRole.Admin).ToString())
            {
                context.Succeed(requirement);
            }
            else
                context.Fail();

        }

        void VipPolicy(AuthorizationHandlerContext context, AdminRequirement requirement)
        {
            var role = context.User.Claims.FirstOrDefault(c => c.Type == "Role")?.Value;
            var grade = context.User.Claims.FirstOrDefault(c => c.Type == "Grade")?.Value;
            var gradeId = Convert.ToInt32(grade);

            if (gradeId > 0 || role == ((int)UserRole.Admin).ToString())
            {
                context.Succeed(requirement);
            }
            else
                context.Fail();
        }

    }
}
